package com.rabbit.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rabbit.constant.ResultCodeEnum;
import com.rabbit.db.entity.*;
import com.rabbit.exception.BusinessException;
import com.rabbit.mapper.DictDataMapper;
import com.rabbit.mapper.DictMapper;
import com.rabbit.redis.annotation.Cacheable;
import com.rabbit.redis.constant.RedisKeyConstant;
import com.rabbit.redis.service.RedisService;
import com.rabbit.service.DictService;
import com.rabbit.vo.req.DictReq;
import com.rabbit.vo.res.DictDataRes;
import com.rabbit.vo.res.DictRes;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <h1>字典管理业务实现类</h1>
 *
 * @author zjw
 * @date 2022/1/20 13:34
 */
@Service
public class DictServiceImpl implements DictService {

    @Resource
    private DictMapper dictMapper;

    @Resource
    private DictDataMapper dictDataMapper;

    @Override
    @Cacheable(key = RedisKeyConstant.SYS_DICT, targetClass = DictDataRes.class, expireType = Cacheable.EXPIRE_TYPE.NEVER)
    public List<DictDataRes> queryDictData() {
        return dictMapper.queryDictData();
    }

    @Override
    public PageInfo<DictRes> queryDictList(DictReq dictReq) {
        Dict dict = Dict.builder().build();
        BeanUtils.copyProperties(dictReq, dict);
        return PageHelper.startPage(dictReq.getPage(), dictReq.getLimit())
                .doSelectPageInfo(() -> dictMapper.queryDictList(dict));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Cacheable(key = RedisKeyConstant.SYS_DICT, cacheType = Cacheable.CACHE_TYPE.UPDATE)
    public void deleteDict(DictReq dictReq) {
        Dict dict = dictMapper.selectByPrimaryKey(dictReq.getDictId());
        DictData dictData = DictData.builder().dictType(dict.getDictType()).build();
        dictDataMapper.delete(dictData);
        dictMapper.deleteByPrimaryKey(dictReq.getDictId());
    }

    @Override
    @Cacheable(key = RedisKeyConstant.SYS_DICT, cacheType = Cacheable.CACHE_TYPE.UPDATE)
    public void updateDictEnabled(DictReq dictReq) {
        Dict dict = Dict.builder().dictId(dictReq.getDictId()).isEnabled(dictReq.getIsEnabled()).updateBy(dictReq.getOperatorUserName()).build();
        dictMapper.updateByPrimaryKeySelective(dict);
    }

    @Override
    public DictRes queryDictById(Long dictId) {
        Dict dict = dictMapper.selectByPrimaryKey(dictId);
        DictRes dictRes = DictRes.builder().build();
        BeanUtils.copyProperties(dict, dictRes);
        return dictRes;
    }

    @Override
    public void checkUnique(DictReq dictReq, int operType) throws BusinessException {
        // 1. 字典名称唯一
        Example dictNameExample = new Example(Dict.class);
        Example.Criteria dictNameCriteria = dictNameExample.createCriteria();
        dictNameCriteria.andEqualTo("dictName", dictReq.getDictName());
        if (operType > 1) {
            dictNameCriteria.andNotEqualTo("dictId", dictReq.getDictId());
        }
        if (dictMapper.selectCountByExample(dictNameExample) > 0) {
            throw new BusinessException(ResultCodeEnum.DICT_NAME_EXISTS_ERROR);
        }
        // 2. 字典类型唯一
        Example dictTypeExample = new Example(Dict.class);
        Example.Criteria dictKeyCriteria = dictTypeExample.createCriteria();
        dictKeyCriteria.andEqualTo("dictType", dictReq.getDictType());
        if (operType > 1) {
            dictKeyCriteria.andNotEqualTo("dictId", dictReq.getDictId());
        }
        if (dictMapper.selectCountByExample(dictTypeExample) > 0) {
            throw new BusinessException(ResultCodeEnum.DICT_TYPE_EXISTS_ERROR);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Cacheable(key = RedisKeyConstant.SYS_DICT, cacheType = Cacheable.CACHE_TYPE.UPDATE)
    public void addDict(DictReq dictReq) {
        Dict dict = Dict.builder().build();
        BeanUtils.copyProperties(dictReq, dict);
        dict.setIsEnabled(true);
        dict.setCreateBy(dictReq.getOperatorUserName());
        dictMapper.insertSelective(dict);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Cacheable(key = RedisKeyConstant.SYS_DICT, cacheType = Cacheable.CACHE_TYPE.UPDATE)
    public void updateDict(DictReq dictReq) {
        Dict dict = Dict.builder().build();
        BeanUtils.copyProperties(dictReq, dict);
        dict.setUpdateBy(dictReq.getOperatorUserName());
        dictMapper.updateByPrimaryKeySelective(dict);
    }

    @Override
    public List<DictRes> queryAllDict() {
        Example dictExample = new Example(Dict.class);
        Example.Criteria dictCriteria = dictExample.createCriteria();
        dictCriteria.andEqualTo("isEnabled", true);
        List<Dict> dicts = dictMapper.selectByExample(dictExample);
        return dicts.stream().map(e -> DictRes.builder().dictName(e.getDictName()).dictType(e.getDictType()).build()).collect(Collectors.toList());
    }
}
